home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / exampleCode / opengl / utilities / isfast / README < prev   
Encoding:
Text File  |  1994-08-02  |  14.1 KB  |  413 lines

  1.  
  2.         ~4Dgifts/toolbox/src/exampleCode/opengl/utilities/isfast README
  3.  
  4.  
  5. ______________________________________________________________________
  6. The Problem
  7.  
  8. When you're writing an OpenGL application, how do you know whether a
  9. particular feature (like depth buffering or texture mapping) is fast
  10. enough to be useful?
  11.  
  12. If you want your application to run fast on a variety of machines,
  13. while taking advantage of as many hardware features as possible, you
  14. need to write code that makes configuration decisions at runtime.
  15.  
  16. For OpenGL's predecessor, IRIS GL, you could call getgdesc() to
  17. determine whether a feature had hardware support.  For example, you
  18. could determine whether a Z buffer existed.  If it did, you might
  19. assume that Z buffering was fast, and therefore your application would
  20. use it.
  21.  
  22. In OpenGL, things are different.  All the core features are provided,
  23. even when there is no hardware support for them and they must be
  24. implemented completely in software.  There is no OpenGL routine that
  25. reports whether a feature is implemented partially or completely in
  26. hardware.
  27.  
  28. Furthermore, features interact in essentially unpredictable ways.  For
  29. example, a machine might have hardware support for depth buffering, but
  30. only for some comparison functions.  Or depth buffering might be fast
  31. only as long as stencilling is not enabled.  Or depth buffering might
  32. be fast when drawing to a window, but slow when drawing to a pixmap.
  33. And so on.  A routine that identifies hardware support for particular
  34. features is actually a lot more complicated and less useful than you'd
  35. like!
  36.  
  37.  
  38.  
  39. ______________________________________________________________________
  40. A Solution
  41.  
  42. So how do you decide whether a given OpenGL feature is fast?  The
  43. answer is "Measure it." Since the performance of a piece of graphics
  44. code is dependent on dozens of pieces of information from the runtime
  45. environment, no other method is as well-defined and reliable.
  46.  
  47. Performance measurement can be tricky.  You need to handle the cases
  48. when you're displaying over a network, as well as locally.  You also
  49. want to think about flushing the graphics pipeline properly, and
  50. accounting for the resulting overhead.
  51.  
  52. Measuring all the features needed by your application might take a
  53. while -- probably too long to make your users wait for the results each
  54. time the application starts.  Therefore you'll want to save performance
  55. measurements and reuse them whenever possible.
  56.  
  57. And you may want to measure things other than graphics:  Disk and
  58. network throughput, processing time for a particular set of data,
  59. performance on uniprocessor and multiprocessor systems.
  60.  
  61. This document describes two libraries that can help with all of the
  62. tasks just mentioned.
  63.  
  64.     libpdb
  65.         "Performance DataBase" routines for measuring execution
  66.         rates and maintaining a simple database.
  67.  
  68.     libisfast
  69.         A set of routines demonstrating libpdb that answer
  70.         common questions about the performance of OpenGL
  71.         features (using entirely subjective criteria).
  72.  
  73. These libraries can't substitute for comprehensive benchmarking and
  74. performance analysis, and don't replace more sophisticated tools (like
  75. IRIS Performer and IRIS Inventor) that optimize application performance
  76. in a variety of ways.  However, they can handle simple tasks, and
  77. that's all some programmers need.
  78.  
  79.  
  80.  
  81. ______________________________________________________________________
  82. libpdb Tutorial
  83.  
  84. libpdb provides five routines:
  85.  
  86.     pdbOpen() opens the performance database.
  87.  
  88.     pdbReadRate() reads the execution rate for a given benchmark
  89.     (identified by a machine name, application name, and benchmark
  90.     name) from the database.
  91.  
  92.     pdbMeasureRate() measures the execution rate for a given
  93.     operation.
  94.  
  95.     pdbWriteRate() writes the execution rate for a given benchmark
  96.     into the database.
  97.  
  98.     pdbClose() closes the performance database and writes it back
  99.     to disk if necessary.
  100.  
  101. All libpdb routines return a value of type pdbStatusT, which is a
  102. bitmask of error conditions.  If the value is zero (PDB_NO_ERROR), then
  103. the call completed successfully.  If the value is nonzero, then it is a
  104. combination of one or more of the following conditions:
  105.  
  106.     PDB_OUT_OF_MEMORY       An attempt to allocate memory failed.
  107.  
  108.     PDB_SYNTAX_ERROR        The database contains one or more
  109.                 records that could not be parsed.
  110.  
  111.     PDB_NOT_FOUND           The database does not contain the
  112.                 record requested by the application.
  113.  
  114.     PDB_CANT_WRITE          The database file could not be
  115.                 updated.
  116.  
  117.     PDB_NOT_OPEN        pdbOpen() was not invoked before
  118.                 calling one of the other libpdb
  119.                 routines.
  120.  
  121.     PDB_ALREADY_OPEN    pdbOpen() was called while the database
  122.                 is still open (e.g., before pdbClose()
  123.                 is invoked).
  124.  
  125. Every program must call pdbOpen() before using the database, and
  126. pdbClose() when the database is no longer needed.  pdbOpen() opens the
  127. database file (stored in $HOME/.pdb on UNIX systems) and reads all the
  128. performance measurements into main memory.  pdbClose() releases all
  129. memory used by the library, and writes the database back to its file if
  130. any changes have been made by invoking pdbWriteRate().
  131.  
  132.     Synopsis
  133.  
  134.         pdbStatusT pdbOpen(void);
  135.  
  136.         pdbStatusT pdbClose(void);
  137.  
  138. pdbOpen() returns PDB_NO_ERROR on success, PDB_OUT_OF_MEMORY if there
  139. was insufficient main memory to store the entire database,
  140. PDB_SYNTAX_ERROR if the contents of the database could not be parsed or
  141. seemed implausible (e.g. a nonpositive performance measurement), or
  142. PDB_ALREADY_OPEN if the database has been opened by a previous call to
  143. pdbOpen() and not closed by a call to pdbClose().
  144.  
  145. pdbClose() returns PDB_NO_ERROR on success, PDB_CANT_WRITE if the
  146. database file is unwriteable for any reason, or PDB_NOT_OPEN if the
  147. database is not open.
  148.  
  149. Normally applications will look for the performance data they need
  150. before going to the trouble of taking measurements.  pdbReadRate() is
  151. used for this.
  152.  
  153.     Synopsis
  154.  
  155.         pdbStatusT pdbReadRate
  156.                 (
  157.                 const char* machineName,
  158.                 const char* applicationName,
  159.                 const char* benchmarkName,
  160.                 double* rate
  161.                 );
  162.     
  163.     Example
  164.  
  165.         main()
  166.             {
  167.             double rate;
  168.             pdbOpen();
  169.             if (pdbReadRate(NULL, "myApp", "triangles", &rate)
  170.                 == PDB_NO_ERROR)
  171.                 printf("%g triangle calls per second\n", rate);
  172.             pdbClose();
  173.             }
  174.  
  175. The first argument is a zero-terminated string giving the name of the
  176. machine for which the measurement is sought.  If NULL, the default
  177. machine name is used.  In X11 environments, the display name is an
  178. appropriate choice, and the default machine name is the content of the
  179. DISPLAY environment variable.
  180.  
  181. The second argument is the name of the application.  This is used as an
  182. additional database key to reduce accidental collisions between
  183. benchmark names.
  184.  
  185. The third argument is the name of the benchmark.
  186.  
  187. None of the string arguments may contain blanks, tabs, or newlines,
  188. as these characters foil the simple-minded parser in pdbOpen().
  189.  
  190. The fourth argument is a pointer to a double-precision floating-point
  191. variable which receives the performance measurement (the "rate") from
  192. the database.  The rate indicates the number of benchmark operations per
  193. second that were measured on a previous run.
  194.  
  195. if pdbReadRate() returns zero, then it completed successfully and the
  196. rate is returned in the last argument.  If the requested benchmark is
  197. not present in the database, it returns PDB_NOT_FOUND.  Finally, if
  198. pdbReadRate() is called when the database has not been opened by
  199. pdbOpen(), it returns PDB_NOT_OPEN.
  200.  
  201. When the application is run for the first time, or when the performance
  202. database file has been removed (perhaps to allow a fresh start after
  203. a hardware upgrade), pdbReadRate() will not be able to find the desired
  204. benchmark.  If this happens, the application should use pdbMeasureRate()
  205. to make a measurement.
  206.  
  207.     Synopsis
  208.  
  209.         typedef void (*pdbCallbackT)();
  210.  
  211.         pdbStatusT pdbMeasureRate
  212.                 (
  213.                 pdbCallbackT initialize,
  214.                 pdbCallbackT operation,
  215.                 pdbCallbackT finalize,
  216.                 double* rate
  217.                 );
  218.     
  219.     Example
  220.  
  221.         void SetupOpenGL(void)
  222.             {
  223.             /* Open window, set up context, etc. */
  224.             }
  225.  
  226.         void DrawTriangles(void)
  227.             {
  228.             glBegin(GL_TRIANGLE_STRIP);
  229.                 /* specify some vertices... */
  230.             glEnd();
  231.             }
  232.         
  233.         main()
  234.             {
  235.             double rate;
  236.             pdbOpen();
  237.             if (pdbReadRate(NULL, "myApp", "triangles", &rate)
  238.                 != PDB_NO_ERROR)
  239.                 {
  240.                 SetupOpenGL();
  241.                 pdbMeasureRate(glFinish, DrawTriangles,
  242.                     glFinish, &rate);
  243.                 }
  244.             printf("%g triangle calls per second\n", rate);
  245.             pdbClose();
  246.             }
  247.  
  248. The first argument is a pointer to an "initialization" function.  This
  249. function is run once, before each set of operations.  In the example,
  250. we used glFinish() to ensure the graphics pipeline is quiescent before
  251. making a measurement.  The initialization routine could also be used
  252. for other purposes; for example, it could preload a cache.  It may be
  253. NULL, in which case no initialization is performed.
  254.  
  255. The second argument is a pointer to an "operation" function.  This
  256. function performs the operations that are to be measured.  Usually
  257. you'll want to set up any global context before calling
  258. pdbMeasureRate(), so that the operation function performs only tasks of
  259. special interest.
  260.  
  261. The third argument is a pointer to a "finalization" function.  This is
  262. run once, after all the calls to the operation function are complete.
  263. In the example above, we used glFinish() again to ensure that the
  264. graphics pipeline is idle.  The finalization function is "calibrated"
  265. and its overhead subtracted from the time required to complete all the
  266. calls to the operation function.  It may be NULL, in which case no
  267. finalization is performed.
  268.  
  269. The final argument is a pointer to a double-precision floating-point
  270. variable which receives the execution rate.  This rate is the number of
  271. times the operation function was called per second.
  272.  
  273. pdbMeasureRate() attempts to compute a number of repetitions that
  274. results in a run time of about one second.  It's reasonably careful
  275. about timekeeping on systems with low-resolution clocks.
  276.  
  277. pdbMeasureRate() always returns PDB_NO_ERROR.
  278.  
  279. Once a rate has been measured, it should be stored in the database
  280. by calling pdbWriteRate().
  281.  
  282.     Synopsis
  283.  
  284.         pdbStatusT pdbWriteRate
  285.                 (
  286.                 const char* machineName,
  287.                 const char* applicationName,
  288.                 const char* benchmarkName,
  289.                 double rate
  290.                 );
  291.     
  292.     Example
  293.  
  294.         main()
  295.             {
  296.             double rate;
  297.             pdbOpen();
  298.             if (pdbReadRate(NULL, "myApp", "triangles", &rate)
  299.                 != PDB_NO_ERROR)
  300.                 {
  301.                 SetupOpenGL();
  302.                 pdbMeasureRate(glFinish, DrawTriangles,
  303.                     glFinish, &rate);
  304.                 pdbWriteRate(NULL, "myApp", "triangles", rate);
  305.                 }
  306.             printf("%g triangle calls per second\n", rate);
  307.             pdbClose();
  308.             }
  309.  
  310. The first three arguments of pdbWriteRate() match the first three
  311. arguments of pdbReadRate().
  312.  
  313. The final argument is the performance measurement to be saved in the
  314. database.
  315.  
  316. pdbWriteRate() will return PDB_NO_ERROR if the performance measurement
  317. was added to the in-memory copy of the database, PDB_OUT_OF_MEMORY if
  318. there was insufficient main memory to do so, or PDB_NOT_OPEN if the
  319. database is not open.
  320.  
  321. When pdbWriteRate() is called, the in-memory copy of the performance
  322. database is marked "dirty."  pdbClose() takes note of this and writes
  323. the database back to disk.
  324.  
  325.  
  326.  
  327. ______________________________________________________________________
  328. libisfast Tutorial
  329.  
  330. libisfast is a set of demonstration routines that show how libpdb can
  331. be used to measure and maintain performance data.  libisfast is based
  332. on some highly subjective personal performance criteria.  If they're
  333. appropriate for your application, please feel free to use them.  If
  334. not, please copy the source code and modify it accordingly.
  335.  
  336. In all cases that follow, the term "triangles" refers to a triangle
  337. strip with 37 vertices.  Each triangle covers approximately 50
  338. pixels.  They're drawn with perspective projection, lighting, and
  339. smooth (Gouraud) shading.  Unless otherwise stated, immediate-mode
  340. drawing is used.
  341.  
  342. DepthBufferingIsFast() returns nonzero if depth buffered triangles can
  343. be drawn at least one-half as fast as triangles without depth
  344. buffering:
  345.  
  346.     int DepthBufferingIsFast(void);
  347.  
  348. ImmediateModeIsFast() returns nonzero if immediate-mode triangles can
  349. be drawn at least one-half as fast as display-listed triangles:
  350.  
  351.     int ImmediateModeIsFast(void);
  352.  
  353. Note that one important use of ImmediateModeIsFast() might be to decide
  354. whether a "local" or a "remote" rendering strategy is appropriate.  If
  355. immediate mode is fast, as on a local workstation, it may be best to
  356. use it and avoid the memory cost of duplicating the application's data
  357. structures in display lists.  If immediate mode is slow, as is likely
  358. for a remote workstation, it may be best to use display lists for bulky
  359. geometry and textures.
  360.  
  361. StencillingIsFast() returns nonzero if stencilled triangles can be
  362. drawn at least one-half as fast as non-stencilled triangles:
  363.  
  364.     int StencillingIsFast(void);
  365.  
  366. TextureMappingIsFast() returns nonzero if texture-mapped triangles can
  367. be drawn at least one-half as fast as non-texture-mapped triangles:
  368.  
  369.     int TextureMappingIsFast(void);
  370.  
  371. Although the routines in libisfast will be useful for a number of
  372. applications, we suggest that you study them and modify them for your
  373. own use.  That way you'll explore the particular performance
  374. characteristics of your machines:  their sensitivity to triangle size,
  375. triangle strip length, culling, stencil function, texture map type,
  376. texture coordinate generation method, etc.
  377.  
  378. Keep in mind that while the results of the libisfast routines are
  379. interesting, they apply to very limited special cases.  You should
  380. always consider using a more general tool like Inventor or Performer.
  381.  
  382.  
  383.  
  384. ______________________________________________________________________
  385. Notes
  386.  
  387. The source directory has four subdirectories:
  388.  
  389.     demo
  390.         Contains a trivial main program to call the routines
  391.         in libisfast.
  392.  
  393.     libisfast
  394.         Source code for libisfast.
  395.  
  396.     libpdb
  397.         Source code for libpdb.
  398.  
  399.     libtk
  400.         Source code for the version of libtk (an unsupported
  401.         but widely-available windowing toolkit) used by
  402.         libisfast.  It includes slight modifications for
  403.         terminating the tk event loop without exiting the
  404.         program, plus a bug fix for creating direct rendering
  405.         contexts.
  406.  
  407. Each subdirectory has its own makefile, and there is a master makefile
  408. in the main source directory.
  409.  
  410. This code has been tested lightly in IRIX 5.1, a UNIX SVR4 environment,
  411. on the following machines:  Indigo R3000 Entry, Indigo2 Extreme, 4D/340
  412. Reality Engine.
  413.